package com.mekya.sensorPlayer;

import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.logging.LogManager;

import android.app.Activity;
import android.content.Context;
import android.graphics.Color;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.ToggleButton;

import com.androidplot.xy.LineAndPointFormatter;
import com.androidplot.xy.LineAndPointRenderer;
import com.androidplot.xy.SimpleXYSeries;
import com.androidplot.xy.XYPlot;


public class SensorPlayer extends Activity {
    private SignalDetector detector = new SignalDetector();
	private TextView recordX;
	private TextView recordY;
	private TextView recordZ;
	private MediaPlayer mp;
	private ArrayList<Float> patternListX = new ArrayList<Float>();
	private ArrayList<Float> patternListY = new ArrayList<Float>();
	private ArrayList<Float> patternListZ = new ArrayList<Float>();
	
	private ArrayList<Float> dataListX = new ArrayList<Float>();
	private ArrayList<Float> dataListY = new ArrayList<Float>();
	private ArrayList<Float> dataListZ = new ArrayList<Float>();
	
	private SensorEventListener patternListener = new SensorEventListener() {
		final float alpha = (float)0.8;
		float gravity[] = new float[3];
		float linear_acceleration[] = new float[3];
		@Override
		public void onSensorChanged(SensorEvent event) {
			if (correlateDataButton.isChecked()) {
				dataListener.onSensorChanged(event);
			}
			else if (recordPatternButton.isChecked()){
				gravity[0] = alpha * gravity[0] + (1 - alpha) * event.values[0];
				gravity[1] = alpha * gravity[1] + (1 - alpha) * event.values[1];
				gravity[2] = alpha * gravity[2] + (1 - alpha) * event.values[2];
				linear_acceleration[0] = event.values[0] - gravity[0];
				linear_acceleration[1] = event.values[1] - gravity[1];
				linear_acceleration[2] = event.values[2] - gravity[2];
				
				//patternX.addLast(linear_acceleration[0]);
				//patternXSeries.setModel(patternX, SimpleXYSeries.ArrayFormat.Y_VALS_ONLY);
				//patternChart.redraw();
				
				patternListX.add(linear_acceleration[0]);
				patternListY.add(linear_acceleration[1]);
				patternListZ.add(linear_acceleration[2]);
				
				//infoView.setText(String.valueOf(patternListX.size()));
				recordX.setText(linear_acceleration[0] + "\n");
				recordY.setText(linear_acceleration[1] + "\n");
				recordZ.setText(linear_acceleration[2] + "\n");

			}
		}
		@Override
		public void onAccuracyChanged(Sensor sensor, int accuracy) {
		}
	};
	int rep = 0;
	private SensorEventListener dataListener = new SensorEventListener() {
		final float alpha = (float)0.8;
		float gravity[] = new float[3];
		float linear_acceleration[] = new float[3];
		@Override
		public void onSensorChanged(SensorEvent event) {		
			gravity[0] = alpha * gravity[0] + (1 - alpha) * event.values[0];
			gravity[1] = alpha * gravity[1] + (1 - alpha) * event.values[1];
			gravity[2] = alpha * gravity[2] + (1 - alpha) * event.values[2];
			linear_acceleration[0] = event.values[0] - gravity[0];
			linear_acceleration[1] = event.values[1] - gravity[1];
			linear_acceleration[2] = event.values[2] - gravity[2];
			  
			dataX.add(linear_acceleration[0]);			
			dataListX.add(linear_acceleration[0]);
			dataListY.add(linear_acceleration[1]);
			dataListZ.add(linear_acceleration[2]);
			
			float[] dataXArray = getDataXArray();
			float[] patternXArray = getPatternXArray(dataXArray.length);
			
			float[] dataYArray = getDataYArray();
			float[] patternYArray = getPatternYArray(dataYArray.length);
			
			float[] dataZArray = getDataZArray();
			float[] patternZArray = getPatternZArray(dataZArray.length);
			
			boolean patternStarted = false;
			float rX, rY, rZ;
			
			try {
				
				if(rep++ > 15) {
					rep = rep++;
				}
				
				rX = detector.getCCCoefficient(dataXArray, patternXArray, dataXArray.length);
				rY = detector.getCCCoefficient(dataYArray, patternYArray, dataYArray.length);
				rZ = detector.getCCCoefficient(dataZArray, patternZArray, dataZArray.length);

				//System.out.println(r);
				coefficientView.setText(rX + ", " + rY +", " + rZ);
				coefficientList.addLast(rX);
				if (rX > 0.9) {
					// if coefficient is above threshold, start playing
					patternStarted = true;
					if (mp.isPlaying() == false) {
				    	mp.start();
					}
					
				}
				else {
					
					if (mp.isPlaying() == true){
						//if coefficient is below threshold, stop playing
						mp.pause();					
					}
					
					if (patternStarted == true) {
						int size = patternListX.size();	
						// dont lose last datas because they can match with pattern's first datas
						for (int j = 0; j < size - detector.getMinDataCount(); j++) {
							dataListX.remove(0);
						}
						patternStarted = false;
					}
					else {

					}
				}
			} catch (Exception e) {
				coefficientList.addLast(-2);
				e.printStackTrace();
			}
			dataXSeries.setModel(dataX, SimpleXYSeries.ArrayFormat.Y_VALS_ONLY);
			coefficientSeries.setModel(coefficientList, SimpleXYSeries.ArrayFormat.Y_VALS_ONLY);
			patternChart.redraw();	
		}
		@Override
		public void onAccuracyChanged(Sensor sensor, int accuracy) {
		}
	};
	private TextView coefficientView;
	private ToggleButton correlateDataButton;
	private XYPlot patternChart;
	private LinkedList<Number> patternX = new LinkedList<Number>();
	private LinkedList<Number> dataX = new LinkedList<Number>();
	private LinkedList<Number> coefficientList = new LinkedList<Number>();
	private SimpleXYSeries patternXSeries = new SimpleXYSeries("Pattern X");
	private SimpleXYSeries dataXSeries = new SimpleXYSeries("Data X");
	private SimpleXYSeries coefficientSeries = new SimpleXYSeries("Coefficients");
	private ToggleButton recordPatternButton;
	private SensorManager sensorManager;
	private Sensor accelerometer;
	
	

	/** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        sensorManager = (SensorManager)getSystemService(Context.SENSOR_SERVICE);

        accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
        
        patternChart = (XYPlot) findViewById(R.id.patternChart);
        
        patternChart.addSeries(patternXSeries, LineAndPointRenderer.class, new LineAndPointFormatter(Color.RED, Color.BLACK, Color.TRANSPARENT));
        patternChart.addSeries(dataXSeries,  LineAndPointRenderer.class, new LineAndPointFormatter(Color.GREEN, Color.MAGENTA, Color.TRANSPARENT));
        patternChart.addSeries(coefficientSeries, LineAndPointRenderer.class, new LineAndPointFormatter(Color.YELLOW, Color.YELLOW, Color.TRANSPARENT));
    //        series1.

      //  patternChart.ad
        patternChart.setTicksPerRangeLabel(3);
        patternChart.disableAllMarkup();

        
        mp = new MediaPlayer();
        try {
			mp.setDataSource("/sdcard/sound.mp3");
			mp.prepare();
		} catch (IllegalArgumentException e1) {
			e1.printStackTrace();
		} catch (IllegalStateException e1) {
			e1.printStackTrace();
		} catch (IOException e1) {
			e1.printStackTrace();
		}
		
	
		recordPatternButton = (ToggleButton) findViewById(R.id.recordPattern);
		recordX = (TextView) findViewById(R.id.valueX);
		recordY = (TextView) findViewById(R.id.valueY);
		recordZ = (TextView) findViewById(R.id.valueZ);

		coefficientView = (TextView) findViewById(R.id.coeffientView);
		
		recordPatternButton.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				if (recordPatternButton.isChecked()) {
					patternListX.clear();
					patternListY.clear();
					patternListZ.clear();
					sensorManager.registerListener(patternListener, accelerometer, SensorManager.SENSOR_DELAY_GAME);
					Toast.makeText(getApplicationContext(), "Start recording", Toast.LENGTH_SHORT).show();
				}
				else {
					sensorManager.unregisterListener(patternListener, accelerometer);
					Toast.makeText(getApplicationContext(), "Pausing", Toast.LENGTH_SHORT).show();
					recordX.append(patternListX.size() + " data collected");
				}
			}
			
		});
		
		correlateDataButton = (ToggleButton) findViewById(R.id.correlateButton);
		correlateDataButton.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				if (correlateDataButton.isChecked()){
					coefficientView.setText("");
					dataListX.clear();
					dataListY.clear();		
					dataListZ.clear();	
					sensorManager.registerListener(dataListener, accelerometer, SensorManager.SENSOR_DELAY_GAME);
				}
				else {
					sensorManager.unregisterListener(dataListener, accelerometer);
				}
			}
		});
    }
    
    
	private float[] getPatternXArray(int length) 
	{
		if (length > patternListX.size()) {
			length = patternListX.size();
		}
		float[] patternArray = new float[length];
		for (int i = 0; i < patternArray.length; i++) {
			patternArray[i] = patternListX.get(i);
		}

		return patternArray;
	}
	
	public float[] getDataXArray() 
	{
		int length = dataListX.size();
		float[] data = new float[length];
		for (int i = 0; i < length; i++) {
			data[i] = dataListX.get(i);
		}
		return data;
	}
	
	private float[] getPatternYArray(int length) 
	{
		if (length > patternListY.size()) {
			length = patternListY.size();
		}
		float[] patternArray = new float[length];
		for (int i = 0; i < patternArray.length; i++) {
			patternArray[i] = patternListY.get(i);
		}

		return patternArray;
	}
	
	public float[] getDataYArray() 
	{
		int length = dataListY.size();
		float[] data = new float[length];
		for (int i = 0; i < length; i++) {
			data[i] = dataListY.get(i);
		}
		return data;
	}
	
	private float[] getPatternZArray(int length) 
	{
		if (length > patternListZ.size()) {
			length = patternListZ.size();
		}
		float[] patternArray = new float[length];
		for (int i = 0; i < patternArray.length; i++) {
			patternArray[i] = patternListZ.get(i);
		}

		return patternArray;
	}
	public float[] getDataZArray() 
	{
		int length = dataListZ.size();
		float[] data = new float[length];
		for (int i = 0; i < length; i++) {
			data[i] = dataListZ.get(i);
		}
		return data;
	}
    
}